/*
 * Flashlib - QB9 common Flash library
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.qb9.flashlib.ai
{
	import com.qb9.flashlib.input.mouse.VirtualMouse;
	import com.qb9.flashlib.motion.MoveTo;
	import com.qb9.flashlib.tasks.Func;
	import com.qb9.flashlib.tasks.Queue;
	import com.qb9.flashlib.tasks.QueueEvent;
	import com.qb9.flashlib.tasks.Wait;
	import com.qb9.flashlib.utils.DisplayUtil;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Point;
	
	public class AIMousePlayer extends EventDispatcher
	{
		public var mouse:VirtualMouse
		protected var data:AIMousePlayerData;
		protected var queue:Queue;
		
		public function AIMousePlayer(data:AIMousePlayerData, mouse:VirtualMouse, queue:Queue)
		{
			this.data = data;
			this.mouse = mouse;			
			this.queue = queue;
		}
		
		public function start() : void
		{
			stop();
			queue.addEventListener(QueueEvent.EMPTY,nextTurn);
			nextTurn();
		}
		
		public function stop() : void
		{
			queue.subtasks.length = 0;
			queue.removeEventListener(QueueEvent.EMPTY,nextTurn);
		}
		
		protected function find() : void
		{
			var ticks:uint = 0;
			do 
				ticks++;
			while (Math.random() > data.successRatio);
				
			think(ticks);
		}
		
		public function think(ticks:uint) : void
		{
			if (ticks)
				queue.add(new Wait(
					ticks * data.tickDuration
				));
		}
		
		protected function act() : void
		{
			then(dispatchEvent, new AIMousePlayerEvent(AIMousePlayerEvent.READY));
		}
		
		protected function nextTurn(e:Event=null) : void
		{
			find();
			act();
		}
		
		public function mouseTo(x:Number, y:Number):void
		{
			mouseToObject({ x:x, y:y });
		}
		
		public function mouseToObject(obj:Object, center:Boolean = false) : void
		{
			if (obj is DisplayObject)
				obj = new Wrapper(DisplayObject(obj), center);

			queue.add(
				new MoveTo(mouse, obj, {
					acceleration: data.movementAcceleration,
					maxVelocity: data.movementMaxSpeed,
					distanceThreshold: data.distanceThreshold
				}) 
			);
		}
		
		public function mouseDown() : void
		{
			then(mouse.press);
		}
		
		public function mouseUp() : void
		{
			then(mouse.release);
		}
		
		public function click() : void
		{
			then(mouse.click);
		}
		
		public function then(fn:Function, ...args) : void
		{
			queue.add(Func.fromArgsArray(fn,args));
		}
	}
}
	import flash.display.DisplayObject;
	import flash.geom.Point;
	import com.qb9.flashlib.utils.DisplayUtil;
	

internal class Wrapper
{
	private var obj:DisplayObject;
	private var center:Boolean;
	
	public function Wrapper(obj:DisplayObject, center:Boolean) : void
	{
		this.obj = obj;
		this.center = center;
	}
	
	private function get coords() : Point
	{
		return DisplayUtil.globalCoords(obj);
	}
	
	public function get x() : Number
	{
		return coords.x + (center ? obj.width/2 : 0);
	}
	
	public function get y() : Number
	{
		return coords.y + (center ? obj.height/2 : 0);
	}
}